/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package GlobalObservingSystem.Mundo.BaseDatos;

import GlobalObservingSystem.Mundo.Coordenada;
import java.sql.*;
import java.util.ArrayList;
import javax.sql.DataSource;

/**
 *
 * @author js.rojas
 */
public class AdministradorBD
{

    // -------------------------------------------------
    // Constantes asociadas a las consultas
    // -------------------------------------------------

    private static final String validarUsuario = "select * from Usuario where Seudonimo = ? and Pass = ?";
    private static final String darUser = "select Seudonimo, Nombre, Email, Pass, TipoUsuario from Usuario where Seudonimo = ?";
    private static final String IngresarUsuario = "insert into Usuario values (?, ?, ?, ?, ?)";
    private static final String eliminarUsuario = "DELETE FROM Usuario WHERE Seudonimo = ?";
    private static final String ingresarEstacion = "insert into Estacion values (?,?)";
    private static final String crearMedida = "insert into Medida values (?,?,?,?,?,?)";
    private static final String consultaZonaFecha = "select * from Medida where latitud = ? and longitud = ? and altitud = ? and fecha = date ?";
    private static final String consultaZonasFechas = "select * from Medida where latitud between ? and ? and longitud between ? and ?  and fecha between date ? and date ?";
    private static final String suscribirCitio = "insert into Subscripcion values (?,?, ?)";

    // -------------------------------------------------
    // Atributos
    // -------------------------------------------------
    public Connection conexion;
    // Si JNDI, declarar dataSource
    /**
     * Objeto que permite obtener conexiones a la base de datos
     */
    private static DataSource dataSource;


    private static AdministradorBD instancia;

    // -------------------------------------------------
    // Constructores
    // -------------------------------------------------
    // -------------------------------------------------
    // Con la opción de JNDI
    // -------------------------------------------------
//    public ConsultaDAO( ) throws Exception
//    {
//        dataSource = ServiceLocator.getInstance( ).getDataSource( );
//    }
//     -------------------------------------------------
//         Si no utiliza JNDI
//     -------------------------------------------------
    private AdministradorBD() {
        conexion = null;
         System.out.println("entro al metodo");
        try {

            final String cadenaConexion = "jdbc:mysql://xue.uniandes.edu.co/s2701b04";      // El url, el usuario y passwd deben estar en un archivo de propiedades.                                         // url: "jdbc:oracle:thin:@chie.uniandes.edu.co:1521:chie10";
            final String usuario = "s2701b04";
            final String clave = "i1ccpt39";
            Class.forName("com.mysql.jdbc.Driver");
            establecerConexionSinJNDI(cadenaConexion, usuario, clave);
                    System.out.println("Entro al metodo");

        } catch (Exception e) {
             System.out.println("catch");
            e.printStackTrace();
        }


    }

    // -------------------------------------------------
    // Métodos
    // -------------------------------------------------
    private void establecerConexionJNDI() throws Exception {
        try {
            conexion = dataSource.getConnection();

        } catch (SQLException exception) {
            throw new Exception("ERROR: ConsultaDAO obteniendo una conexin.");
        }
                          finally
           {
               if (conexion != null)
               {
                   try
                   {
                       conexion.close ();
                       System.out.println ("Database connection terminated");
                   }
                   catch (Exception e) { /* ignore close errors */ }
               }
           }
    }

    private void establecerConexionSinJNDI(String url, String usuario, String clave) throws Exception {
        try {
            conexion = DriverManager.getConnection(url, usuario, clave);
             System.out.println ("Database connection established");
        } catch (SQLException exception) {
            throw new Exception("ERROR: ConsultaDAO obteniendo una conexin.");
        }
    }

    /**
     *Cierra la conexión activa a la base de datos. Además, con=null.
     * @param con objeto de conexión a la base de datos
     * @throws VirtualMarcheException Si se presentan errores de conexión
     */
    public void closeConnection(Connection connection) throws Exception {
        try {
            connection.close();
            connection = null;
        } catch (SQLException exception) {
            throw new Exception("ERROR: ConsultaDAO: closeConnection() = cerrando una conexión.");
        }
    }

    // -------------------------------------------------
    // Consultas
    // -------------------------------------------------
    public UsuarioBD validarUsuario(String seudonimo, String passw) throws Exception {
        PreparedStatement prepStmt = null;
        UsuarioBD nuevoUser = null;
        try {
            prepStmt = conexion.prepareStatement(validarUsuario);
            prepStmt.setString(1, seudonimo);
            prepStmt.setString(2, passw);
            ResultSet rs = prepStmt.executeQuery();
            while(rs.next()){
            nuevoUser = new UsuarioBD();
            String seudo = rs.getString(1);
            String nombre = rs.getString(2);
            String email = rs.getString(3);
            String passwd = rs.getString(4);
            String tipo = rs.getString(5);
            nuevoUser.setSeudonimo(seudo);
            nuevoUser.setNombre(nombre);
            nuevoUser.setPasswd(passwd);
            nuevoUser.setEmail(email);
            nuevoUser.setTipoUsuario(tipo);
            }
        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
        return nuevoUser;
    }


     public UsuarioBD darUserSeudonimo(String seudonimo) throws Exception {
        PreparedStatement prepStmt = null;
        UsuarioBD nuevoUser = null;
        try {
            prepStmt = conexion.prepareStatement(darUser);
            prepStmt.setString(1, seudonimo);
            ResultSet rs = prepStmt.executeQuery();
            while(rs.next()){
            nuevoUser = new UsuarioBD();
            String seudo = rs.getString(1);
            String nombre = rs.getString(2);
            String email = rs.getString(3);
            String passwd = rs.getString(4);
            String tipo = rs.getString(5);
            nuevoUser.setSeudonimo(seudo);
            nuevoUser.setNombre(nombre);
            nuevoUser.setPasswd(passwd);
            nuevoUser.setEmail(email);
            nuevoUser.setTipoUsuario(tipo);
            }

        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
        return nuevoUser;
    }

          public boolean eliminarUser(String seudonimo) throws Exception {
        PreparedStatement prepStmt = null;
        boolean elimino = false;
        try {
            prepStmt = conexion.prepareStatement(eliminarUsuario);
            prepStmt.setString(1, seudonimo);
            elimino = prepStmt.execute();
            elimino = true;
        } catch (SQLException exception) {
            closeConnection(conexion);
            throw new Exception(exception);
        }
        return elimino;
    }

    public void ingresarUsuario(String seudonimo, String passw, String tipo, String nombre, String email ) throws Exception {
        PreparedStatement prepStmt = null;
        try {
            prepStmt = conexion.prepareStatement(IngresarUsuario);
            prepStmt.setString(1, seudonimo);
            prepStmt.setString(2, nombre);
            prepStmt.setString(3, email);
            prepStmt.setString(4, passw);
            prepStmt.setString(5, tipo);
            prepStmt.execute();
        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
    }

    public void ingresarEstacion(int id, String nombre) throws Exception {
        PreparedStatement prepStmt = null;
        try {
            prepStmt = conexion.prepareStatement(ingresarEstacion);
            prepStmt.setInt(1, id);
            prepStmt.setString(2, nombre);
            prepStmt.execute();
        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
    }

       public void ingresarMedida(double lati, double longi, double alti, int tipo, Date fecha, int valor) throws Exception {
        PreparedStatement prepStmt = null;
        try {
            prepStmt = conexion.prepareStatement(crearMedida);
            prepStmt.setDouble(1, lati);
            prepStmt.setDouble(2, longi);
            prepStmt.setDouble(3, alti);
            prepStmt.setInt(4, tipo);
            prepStmt.setDate(5, fecha);
            prepStmt.setInt(6, valor);
            prepStmt.execute();
        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
    }

        public ArrayList<MedidaBD> darMedidaZonaFecha(double lat, double lon, double alt, Date fecha) throws Exception {
        PreparedStatement prepStmt = null;
        MedidaBD nuevaMedida = null;
        ArrayList<MedidaBD> lista = new ArrayList<MedidaBD>();
        try {
//select * from Medida where latitud = ? and longitud = ? and altitud = ? and fecha = date ?
            prepStmt = conexion.prepareStatement(consultaZonaFecha);
            prepStmt.setDouble(1, lat);
            prepStmt.setDouble(2, lon);
            prepStmt.setDouble(3, alt);
            prepStmt.setDate(4, fecha);
            ResultSet rs = prepStmt.executeQuery();
            while(rs.next()){
            double latitud = rs.getDouble(1);
            double longitud = rs.getDouble(2);
            double altitud = rs.getDouble(3);
            int tipo = rs.getInt(4);
            Date fech = rs.getDate(5);
            int valor = rs.getInt(6);
            nuevaMedida = new MedidaBD(darCoordenada(latitud),darCoordenada(longitud), (int)altitud, tipo, fech, valor);
            lista.add(nuevaMedida);
            }

        } catch (SQLException exception) {
            throw new Exception(exception);
        } 
        return lista;
    }

    public  ArrayList<MedidaBD> darMedidaZonasFechas(double lat1, double lon1, java.util.Date fecha1, double lat2, double lon2, java.util.Date fecha2) throws Exception {
        PreparedStatement prepStmt = null;
        MedidaBD nuevaMedida = null;
        ArrayList<MedidaBD> lista = new ArrayList<MedidaBD>();
        try {
//select * from Medida where latitud between ? and ? and longitud between ? and ? and altitud ? and fecha between date ? and date ?
            prepStmt = conexion.prepareStatement(consultaZonasFechas);
            prepStmt.setDouble(1, lat1);
            prepStmt.setDouble(2, lat2);
            prepStmt.setDouble(3, lon1);
            prepStmt.setDouble(4, lon2);
            prepStmt.setDate(5, (java.sql.Date)fecha1);
            prepStmt.setDate(6, (java.sql.Date)fecha2);
            ResultSet rs = prepStmt.executeQuery();
            while(rs.next()){
            double latitud = rs.getDouble(1);
            double longitud = rs.getDouble(2);
            double altitud = rs.getDouble(3);
            int tipo = rs.getInt(4);
            Date fech = rs.getDate(5);
            int valor = rs.getInt(6);
            nuevaMedida = new MedidaBD(darCoordenada(latitud),darCoordenada(longitud), (int)altitud, tipo, fech, valor);
            lista.add(nuevaMedida);
            }

        } catch (SQLException exception) {
            throw new Exception(exception);
        
        }
        return lista;
    }

    public ArrayList<MedidaBD> darMedidaArea(double lat, double lon, double alt, Date fecha, short area) throws Exception
    {
        ArrayList<MedidaBD> lista = new ArrayList<MedidaBD>();
        for (int i = 0; i < area; i++) {
            for (int j = 0; j < area; j++) {
                lista.addAll(darMedidaZonaFecha(lat, lon, alt, fecha));
            }
            
        }
        return lista;
    }

        public void suscripcion(String seudo, double lati, double longi ) throws Exception {
        PreparedStatement prepStmt = null;
        try {
            prepStmt = conexion.prepareStatement(suscribirCitio);
            prepStmt.setString(1, seudo);
            prepStmt.setDouble(2, lati);
            prepStmt.setDouble(3, longi);
            prepStmt.execute();
        } catch (SQLException exception) {
            throw new Exception(exception);
        }
    }

    private Coordenada darCoordenada(Double medicion)
    {
        //TODO
        return null;
    }

//    public static void main(String[] args) {
//        AdministradorBD g = new AdministradorBD();
//    }

    public static AdministradorBD getInstance()
	{
		if( instancia == null )
			instancia = new AdministradorBD( );
		return instancia;
	}


}
